package com.gzhryc.net_marketing.supplier;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.api.DefaultAPICodeConstants;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.ConnectionFactory;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.jdbc.enums.DbType;
import com.gzhryc.jdbc.models.ConnectInfo;
import com.gzhryc.jdbc.utils.DbUtils;
import com.gzhryc.net_marketing.api.ConfigAPIService;
import com.gzhryc.net_marketing.api.protocol.config.MarketSupplierConfigResponse;
import com.gzhryc.shared_device.common.BusyThreadPool;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.Base64;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class SupplierManager {

    static Logger log = Logger.getLogger(SupplierManager.class);

    private static ThreadLocal<Long> TL_SupplierId = new ThreadLocal<Long>(); // 当前线程的项目ID

    public static ConcurrentHashMap<Long,Supplier> suppliers = new ConcurrentHashMap<>();

    public static void initial(String token,SupplierInitialListener listener) {
    	MarketSupplierConfigResponse configResponse = ConfigAPIService.self().getMarketSupplierConfig(token);
        if (configResponse != null && DefaultAPICodeConstants.SUCCESS.equals(configResponse.getCode())) {
            if (configResponse.getBody().getItems() != null && configResponse.getBody().getItems().size() > 0) {
                for (MarketSupplierConfigResponse.SupplierItem supplierItem : configResponse.getBody().getItems()) {
                    if (StringTools.isNotBlank(supplierItem.getDbConfig())) {
                        Supplier.DBConfig dbConfig = null;
                        try {
                            String dbConfigJson = new String(Base64.decodeBase64(supplierItem.getDbConfig()), "UTF-8");
                            dbConfig = JsonTools.fromJson(dbConfigJson, Supplier.DBConfig.class);
                        } catch (UnsupportedEncodingException e) {
                            log.error("转换数据库配置错误", e);
                        }
                        if (dbConfig != null && StringUtils.isNotBlank(dbConfig.getIp()) && StringUtils.isNotBlank(dbConfig.getDbName())) {
                        	Supplier supplier = new Supplier();
                        	supplier.setId(supplierItem.getId());
                        	supplier.setName(supplierItem.getName());
                        	supplier.setDbConfig(dbConfig);
                           
                        	supplier.setAccountId(supplierItem.getAccountId());
                        	supplier.setVisitToken(supplierItem.getVisitToken());
                        	supplier.setPayToken(supplierItem.getPayToken());
                        	
                        	supplier.setUserId(supplierItem.getUserId());
                            
                        	supplier.setCreateDate(supplierItem.getCreateDate());

                            ConnectInfo info = createConnectInfo(supplier);
                            BusyThreadPool.self().execute(new InitialDataThread(supplier, info, listener));
                        }
                    }
                }
            }
        }
    }

    public static ConnectInfo createConnectInfo(Supplier supplier) {
    	// 检查并初始化数据库
        ConnectInfo info = new ConnectInfo(DbType.valueOf(supplier.getDbConfig().getDbType()), supplier.getDbConfig().getIp(),
        		supplier.getDbConfig().getPort(), supplier.getDbConfig().getDbName(), supplier.getDbConfig().getUserName(),
        		supplier.getDbConfig().getPassword());
        info.setMaxActive(50);
        info.setMaxIdle(30);
        info.setMaxWait(13000);        //13秒
        info.setRemoveAbandoned(true);
        info.setRemoveAbandonedTimeout(180);
        info.setKey("market_supplier_" + supplier.getId());
        ConnectionFactory.addDataSource(info.getKey(), info);
        supplier.setJdbcKey(info.getKey());
        log.info(supplier.getId() + "项目初始化数据源：IP=" + info.getIp() + ",port=" + info.getPort() + ",DbName=" + info.getDbName() + ",userName="
                + info.getUserName() + ",password=" + info.getPassword());
        suppliers.put(supplier.getId(), supplier);
        return info;
    }
    
    /**
     * 初始化数据库和表
     *
     * @param info
     */
    public static void createDBAndTable(ConnectInfo info) {
        DbUtils.createDatabase(info);
        DbUtils.createTable(info, "com.gzhryc.net_marketing.supplier.config.dao.db");
        DbUtils.createTable(info, "com.gzhryc.net_marketing.supplier.erp.dao.db");
        DbUtils.createTable(info, "com.gzhryc.net_marketing.supplier.pay.dao.db");
    }

    public static Supplier getSupplier() {
        Long supplierId = TL_SupplierId.get();
        if (supplierId != null) {
            return getSupplier(supplierId);
        }
        return null;
    }

    public static Supplier getSupplier(Long supplierId) {
        return suppliers.get(supplierId);
    }
    
    public static Supplier getSupplierByUserId(Long userId) {
    	for(Supplier supplier : suppliers.values()) {
    		if(supplier.getUserId().equals(userId)) {
    			return supplier;
    		}
    	}
        return null;
    }

    public static List<Supplier> getSuppliers(){
        return new ArrayList<>(suppliers.values());
    }

    /**
     * 设置当前线程中的供货商ID
     *
     * @param projectId
     */
    public static boolean setCurrentSupplierId(Long supplierId) {
    	TL_SupplierId.remove();
        // 检查是否存在
        Supplier supplier = suppliers.get(supplierId);
        if (supplier != null) {
        	TL_SupplierId.set(supplierId);
            return true;
        }
        return false;
    }

    /**
     * 移除当前线程中的供货商ID
     */
    public static void removeCurrentSupplierId() {
    	TL_SupplierId.remove();
    }

    public static interface SupplierInitialListener {

        public void execute(Supplier supplier,ConnectInfo info);
    }

    private static class InitialDataThread implements Runnable {

        Supplier project;
        ConnectInfo info;
        SupplierInitialListener listener;

        public InitialDataThread(Supplier project,ConnectInfo info,SupplierInitialListener listener) {
            this.project = project;
            this.info = info;
            this.listener = listener;
        }

        public void run() {
            log.info("设置JdbcKey = " + info.getKey());
            MultiDBTools.setJdbcKey(info.getKey());
            try {
                if (listener != null) {
                    listener.execute(project,info);
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                MultiDBTools.removeJdbcKey();
            }
        }
    }
}
